package com.lm.controller;

import com.lm.model.CheckCode;
import com.lm.model.LmUserLogin;
import com.lm.service.CheckCodeService;
import com.lm.service.LmUserLoginService;
import com.meirengu.common.PasswordEncryption;
import com.meirengu.common.RedisClient;
import com.meirengu.common.StatusCode;
import com.meirengu.controller.BaseController;
import com.meirengu.model.Result;
import com.meirengu.utils.RequestUtil;
import com.meirengu.utils.StringUtil;
import com.meirengu.utils.ValidatorUtil;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

@RestController
public class LoginController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    CheckCodeService checkCodeService;
    @Autowired
    LmUserLoginService lmUserLoginService;
    @Autowired
    private RedisClient redisClient;

    /**
     * 注册
     */
    @RequestMapping(value = "register", method = RequestMethod.POST)
    public Result register(HttpServletRequest request,
                           @RequestParam(value = "phone", required = false) String phone,
                           @RequestParam(value = "check_code", required = false) Integer checkCode,
                           @RequestParam(value = "password", required = false) String password,
                           @RequestParam(value = "device_id", required = false) String deviceId,
                           @RequestParam(value = "cid", required = false) String channelCode,
                           @RequestParam(value = "icode", required = false) String icode,
                           @RequestParam(value = "platform", required = false) Integer platform,
                           @RequestParam(value = "platform_code", required = false) String platformCode) {
        try {
            String ip = RequestUtil.getClientIp(request);
            String userAgent = request.getHeader("user-agent");
            logger.info("LoginController.register params >> mobile:{} device_id :{} time:{} ip :{} userAgent:{}", phone, deviceId, new Date(), ip, userAgent);
            //verify params
            if (StringUtils.isEmpty(phone) || !ValidatorUtil.isMobile(phone)) {
                return super.setResult(StatusCode.MOBILE_FORMAT_ERROR, null, StatusCode.codeMsgMap.get(StatusCode.MOBILE_FORMAT_ERROR));
            }
            if (checkCode == null && password == null) {
                return super.setResult(StatusCode.CHECK_CODE_AND_PASSWORD_NOT_EMPTY, null, StatusCode.codeMsgMap.get(StatusCode.CHECK_CODE_AND_PASSWORD_NOT_EMPTY));
            }

            //手机密码注册校验
            String redisCode = redisClient.get("register_" + phone);
            logger.info("redisCode <==={}", redisCode);
            //先从redis中认证
            if (StringUtils.isNotBlank(redisCode)) {
                if (!redisCode.equals(checkCode.toString())) {
                    return super.setResult(StatusCode.CAPTCHA_INVALID, null, StatusCode.codeMsgMap.get(StatusCode.CAPTCHA_INVALID));
                }
            } else {
                //验证验证码注册 功能：校验验证码有效性  处理验证码已使用
                CheckCode code = checkCodeService.retrieve(phone, Integer.valueOf(checkCode));
                if (code == null) {
                    return super.setResult(StatusCode.CAPTCHA_INVALID, null, StatusCode.codeMsgMap.get(StatusCode.CAPTCHA_INVALID));
                }
                if (code.getExpireTime().compareTo(new Date()) < 0) {
                    return super.setResult(StatusCode.CAPTCHA_EXPIRE, null, StatusCode.codeMsgMap.get(StatusCode.CAPTCHA_EXPIRE));
                }
                code.setUse(true);
                code.setUsingTime(new Date());
                int updateResult = checkCodeService.update(code);
                logger.info("LoginController.register update code result:{}", updateResult);
            }

            //验证手机号是否注册
            LmUserLogin user = lmUserLoginService.detailByPhone(phone);
            if (user != null) {
                return super.setResult(StatusCode.USER_IS_EXITS, null, StatusCode.codeMsgMap.get(StatusCode.USER_IS_EXITS));
            } else {
                //注册
                user = lmUserLoginService.createUser(phone, password, channelCode, icode, platform, platformCode, ip, userAgent);
                user.setPassword("");
                if (user != null) {
                    return super.setResult(StatusCode.OK, user, StatusCode.codeMsgMap.get(StatusCode.OK));
                } else {
                    return super.setResult(StatusCode.REGISTER_IS_FAILED, null, StatusCode.codeMsgMap.get(StatusCode.REGISTER_IS_FAILED));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            String params = String.format("参数:phone:%s,checkCode:%s,password:%s,deviceId:%s,channelCode:%s,icode:%s" +
                    "platform:%s,platformCode:%s", phone, checkCode, password, deviceId, channelCode, icode, platform, platformCode);
            logger.error("LoginController register throws Exceprion :{} happens. params:{}.", ExceptionUtils.getFullStackTrace(e), params);
            return super.setResult(StatusCode.INTERNAL_SERVER_ERROR, null, StatusCode.codeMsgMap.get(StatusCode.INTERNAL_SERVER_ERROR));
        }
    }

    /**
     * 用户登陆接口
     *
     * @param phone
     * @param openId
     * @param token
     * @param checkCode
     * @param password
     * @return
     */
    @RequestMapping(value = "login", method = RequestMethod.POST)
    public Result login(HttpServletRequest request,
                        @RequestParam(value = "phone", required = false) String phone,
                        @RequestParam(value = "openid", required = false) String openId,
                        @RequestParam(value = "token", required = false) String token,
                        @RequestParam(value = "check_code", required = false) Integer checkCode,
                        @RequestParam(value = "password", required = false) String password,
                        @RequestParam(value = "device_id", required = false, defaultValue = "") String deviceId,
                        @RequestParam(value = "cid", required = false) String channelCode,
                        @RequestParam(value = "icode", required = false) String icode,
                        @RequestParam(value = "platform", required = false) Integer platform,
                        @RequestParam(value = "platform_code", required = false) String platformCode) {
        try {
            String ip = RequestUtil.getClientIp(request);
            String userAgent = request.getHeader("user-agent");
            logger.info("LoginController.login params >> mobile:{}, checkCode:{}, password:{}, from:{}, ip:{} deviceId:{} time :{}",
                    new Object[]{phone, checkCode, password, ip, deviceId, new Date()});
            //verify params
            if (StringUtils.isEmpty(phone) || !ValidatorUtil.isMobile(phone)) {
                return super.setResult(StatusCode.MOBILE_FORMAT_ERROR, null, StatusCode.codeMsgMap.get(StatusCode.MOBILE_FORMAT_ERROR));
            }
            if (checkCode == null && password == null) {
                return super.setResult(StatusCode.CHECK_CODE_AND_PASSWORD_NOT_EMPTY, null, StatusCode.codeMsgMap.get(StatusCode.CHECK_CODE_AND_PASSWORD_NOT_EMPTY));
            }

            //密码登陆
            if (!StringUtil.isEmpty(password) && !StringUtil.isEmpty(phone)) {
                LmUserLogin lmUserLogin = lmUserLoginService.detailByPhone(phone);
                if (lmUserLogin != null && vertifyPassword(password, lmUserLogin)) {
                    lmUserLoginService.updateLogin(lmUserLogin, platform, ip);
                    lmUserLogin.setPassword("");
                    return super.setResult(StatusCode.OK, lmUserLogin, StatusCode.codeMsgMap.get(StatusCode.OK));
                } else {
                    return super.setResult(StatusCode.INVALID_USERNAME_OR_PASSWORD, null, StatusCode.codeMsgMap.get(StatusCode.INVALID_USERNAME_OR_PASSWORD));
                }
            }

            //验证码登陆
            if (!StringUtil.isEmpty(checkCode) && !StringUtil.isEmpty(phone)) {
                CheckCode code = checkCodeService.retrieve(phone, Integer.valueOf(checkCode));
                if (code == null) {
                    return super.setResult(StatusCode.CAPTCHA_INVALID, null, StatusCode.codeMsgMap.get(StatusCode.CAPTCHA_INVALID));
                }
                if (code.getExpireTime().compareTo(new Date()) < 0) {
                    return super.setResult(StatusCode.CAPTCHA_EXPIRE, null, StatusCode.codeMsgMap.get(StatusCode.CAPTCHA_EXPIRE));
                }
                code.setUse(true);
                code.setUsingTime(new Date());
                int updateResult = checkCodeService.update(code);
                logger.info("LoginController.login update code result:{}", updateResult);

                //如果没有注册 给用户注册一个用户
                LmUserLogin lmUserLogin = lmUserLoginService.detailByPhone(phone);
                if (lmUserLogin == null) {
                    lmUserLogin = lmUserLoginService.createUser(phone, checkCode.toString(), channelCode, icode, platform, platformCode, ip, userAgent);
                    lmUserLogin.setPassword("");
                } else {
                    lmUserLoginService.updateLogin(lmUserLogin, platform, ip);
                }
                return super.setResult(StatusCode.OK, lmUserLogin, StatusCode.codeMsgMap.get(StatusCode.OK));
            } else {
                return super.setResult(StatusCode.LOGIN_FAILED, null, StatusCode.codeMsgMap.get(StatusCode.LOGIN_FAILED));
            }
        } catch (Exception e) {
            e.printStackTrace();
            String params = String.format("参数:phone:%s,openId:%s,token:%s,checkCode:%s,password:%s,deviceId:%s" +
                    "channelCode:%s,icode:%s,platform:%s,platformCode:%s", phone, openId, token, checkCode, password, deviceId, channelCode, icode, platform, platformCode);
            logger.error("LoginController login throws Exceprion :{} happens. params:{}.", ExceptionUtils.getFullStackTrace(e), params);
            return super.setResult(StatusCode.UNKNOWN_EXCEPTION, null, StatusCode.codeMsgMap.get(StatusCode.UNKNOWN_EXCEPTION));
        }
    }


    public Boolean vertifyPassword(String password, LmUserLogin lmUserLogin) {
        try {
            Boolean result = PasswordEncryption.validatePassword(password, lmUserLogin.getPassword());
            return result;
        } catch (Exception e) {
            logger.error("Common.validatePassword throws Exception :{}", e.getMessage());
            return false;
        }
    }
}
